/**
 * 上传前验证文件
 * @param files
 * @param param1
 */
export const validFiles = (files, { sizeLimit = 9999 }) => {
  const result = {
    status: 0,
    message: '',
  };
  if (!Array.isArray(files) || files.length <= 0) return result;

  for (const { size } of files) {
    if (size / 1024 / 1024 > sizeLimit) {
      result.status = 1;
      result.message = `图片尺寸超过${sizeLimit}MB，请重新选择`;
      break;
    }
  }
  return result;
};

export const replaceFile = (newFile, oldFile, fileList) => {
  const newFileList = [...fileList];
  const index = fileList.findIndex((item) => item.uid === oldFile.uid);
  if (index >= 0) {
    newFileList.splice(index, 1, newFile);
  }
  return newFileList;
};

export const removeFile = (oldFile, fileList) => {
  const newFileList = [...fileList];
  const index = fileList.findIndex((item) => item.uid === oldFile.uid);
  if (index >= 0) {
    newFileList.splice(index, 1);
  }
  return newFileList;
};

export const getFileIndex = (file, fileList) => {
  const index = fileList.findIndex((item) => item.uid === file.uid);
  return index;
};

export const getFile = (file, fileList) => {
  const index = getFileIndex(file, fileList);
  if (index >= 0) {
    return fileList[index];
  }
  return false;
};

export const getBase64 = (file) => {
  return new Promise<string | ArrayBuffer>((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
};

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

function getError(option, xhr) {
  const errorText = codeMessage[xhr.status] || xhr.statusText;
  const msg = `${errorText}, 状态码： ${xhr.status}，url: ${option.url}`;
  const err = new Error(msg);
  err.status = xhr.status;
  err.method = option.method;
  err.url = option.url;
  return err;
}

function getBody(xhr) {
  const text = xhr.responseText || xhr.response;
  if (!text) {
    return text;
  }

  try {
    return JSON.parse(text);
  } catch (e) {
    return text;
  }
}

// option {
//  onProgress: (event: { percent: number }): void,
//  onError: (event: Error, body?: Object): void,
//  onSuccess: (body: Object): void,
//  data: Object,
//  filename: String,
//  file: File,
//  withCredentials: Boolean,
//  url: String,
//  headers: Object,
// }
export const upload = (option) => {
  // eslint-disable-next-line no-undef
  const xhr = new XMLHttpRequest();

  if (option.onProgress && xhr.upload) {
    xhr.upload.onprogress = function progress(e) {
      if (e.total > 0) {
        e.percent = (e.loaded / e.total) * 100;
      }
      option.onProgress(e);
    };
  }

  // eslint-disable-next-line no-undef
  const formData = new FormData();
  if (option.data) {
    Object.keys(option.data).forEach((key) => {
      const value = option.data[key];
      // support key-value array data
      if (Array.isArray(value)) {
        value.forEach((item) => {
          // { list: [ 11, 22 ] }
          // formData.append('list[]', 11);
          formData.append(`${key}[]`, item);
        });
        return;
      }

      formData.append(key, option.data[key]);
    });
  }

  // eslint-disable-next-line no-undef
  if (option.file instanceof Blob) {
    formData.append(option.filename, option.file, option.file.name);
  } else {
    formData.append(option.filename, option.file);
  }

  xhr.onerror = function error(e) {
    console.log(e, 'error1');
    option.onError(e);
  };

  xhr.onload = function onload() {
    // allow success when 2xx status
    // see https://github.com/react-component/upload/issues/34
    if (xhr.status < 200 || xhr.status >= 300) {
      console.log(getError(option, xhr), getBody(xhr), 'error2');
      return option.onError(getError(option, xhr), getBody(xhr));
    }

    return option.onSuccess(getBody(xhr), xhr);
  };

  xhr.open(option.method, `/api${option.url}`, true);

  // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
  if (option.withCredentials && 'withCredentials' in xhr) {
    xhr.withCredentials = true;
  }

  const headers = option.headers || {};

  // when set headers['X-Requested-With'] = null , can close default XHR header
  // see https://github.com/react-component/upload/issues/33
  if (headers['X-Requested-With'] !== null) {
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  }

  Object.keys(headers).forEach((h) => {
    if (headers[h] !== null) {
      xhr.setRequestHeader(h, headers[h]);
    }
  });

  xhr.send(formData);

  return {
    abort() {
      xhr.abort();
    },
  };
};

export const uid = (len = 8, radix = 16): string => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  const value: string[] = [];
  const newRadix = radix || chars.length;

  if (len) {
    // Compact form
    for (let i = 0; i < len; i += 1) {
      // eslint-disable-next-line no-bitwise
      value[i] = chars[0 | (Math.random() * newRadix)];
    }
  } else {
    // rfc4122, version 4 form
    let r;

    // rfc4122 requires these characters
    /* eslint-disable-next-line */
    value[8] = value[13] = value[18] = value[23] = '-';
    value[14] = '4';

    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (let i = 0; i < 36; i += 1) {
      if (!value[i]) {
        // eslint-disable-next-line no-bitwise
        r = 0 | (Math.random() * 16);
        // eslint-disable-next-line no-bitwise
        value[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r];
      }
    }
  }

  return value.join('');
};

export const compress = (file, pictureQuality) =>
  new Promise((resolve) => {
    // 声明FileReader文件读取对象
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      // 生成canvas画布
      const canvas = document.createElement('canvas');
      // 生成img
      const img = document.createElement('img');
      img.src = reader.result as string;
      img.onload = () => {
        const ctx = canvas.getContext('2d');
        // 原始图片宽度、高度
        const { width: originImageWidth, height: originImageHeight } = img;
        // 默认最大尺度的尺寸限制在（1920 * 1080）
        const maxWidth = 1920;
        const maxHeight = 1080;
        const ratio = maxWidth / maxHeight;
        // 目标尺寸
        let targetWidth = originImageWidth;
        let targetHeight = originImageHeight;
        // 当图片的宽度或者高度大于指定的最大宽度或者最大高度时,进行缩放图片
        if (originImageWidth > maxWidth || originImageHeight > maxHeight) {
          // 超过最大宽高比例
          if (originImageWidth / originImageHeight > ratio) {
            // 宽度取最大宽度值maxWidth,缩放高度
            targetWidth = maxWidth;
            targetHeight = Math.round(maxWidth * (originImageHeight / originImageWidth));
          } else {
            // 高度取最大高度值maxHeight,缩放宽度
            targetHeight = maxHeight;
            targetWidth = Math.round(maxHeight * (originImageWidth / originImageHeight));
          }
        }
        // canvas对图片进行缩放
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // 清除画布
        ctx.clearRect(0, 0, targetWidth, targetHeight);
        // 绘制图片
        ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
        // quality值越小,图像越模糊,默认图片质量为0.92
        const imageDataURL = canvas.toDataURL(file.type || 'image/jpeg', pictureQuality);
        // 去掉URL的头,并转换为byte
        const imageBytes = window.atob(imageDataURL.split(',')[1]);
        // 处理异常,将ascii码小于0的转换为大于0
        const arrayBuffer = new ArrayBuffer(imageBytes.length);
        const uint8Array = new Uint8Array(arrayBuffer);
        // eslint-disable-next-line no-plusplus
        for (let i = 0; i < imageBytes.length; i++) {
          uint8Array[i] = imageBytes.charCodeAt(i);
        }
        const mimeType = imageDataURL.split(',')[0].match(/:(.*?);/)[1];
        const newFile = new File([uint8Array], file.name, { type: mimeType || 'image/jpeg' });
        // console.log('after compress, the file size is : ', (newFile.size / 1024 / 1024) + "M");
        resolve(newFile);
      };
    };
    reader.onerror = () => {
      return file;
    };
  })
    .then((res) => {
      return res;
    })
    .catch(() => {
      return file;
    });

export const checkIsImage = (fileName) => {
  let flag;
  const imageTypeList = ['.jpg', '.png', '.jpeg', '.gif', '.GIF', '.JPG', '.PNG', '.JPEG'];
  for (const item of imageTypeList) {
    flag = fileName.indexOf(item) !== -1;
    if (flag) {
      return true;
    }
  }
  return flag;
};
